package com.smart.community.commons.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

/**
 * JSON工具类
 * @author Wu.Liang
 * @since 2024-12-19
 * @version 1.0.0
 */
@Slf4j
public class JsonUtils {
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    /**
     * 对象转JSON字符串
     * 
     * @param obj 对象
     * @return JSON字符串
     */
    public static String toJson(Object obj) {
        if (obj == null) {
            return null;
        }
        
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("对象转JSON失败: {}", obj, e);
            return null;
        }
    }
    
    /**
     * 对象转格式化的JSON字符串
     * 
     * @param obj 对象
     * @return 格式化的JSON字符串
     */
    public static String toPrettyJson(Object obj) {
        if (obj == null) {
            return null;
        }
        
        try {
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("对象转格式化JSON失败: {}", obj, e);
            return null;
        }
    }
    
    /**
     * JSON字符串转对象
     * 
     * @param json JSON字符串
     * @param clazz 对象类型
     * @param <T> 泛型
     * @return 对象
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        if (StringUtils.isEmpty(json) || clazz == null) {
            return null;
        }
        
        try {
            return objectMapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            log.error("JSON转对象失败: json={}, class={}", json, clazz, e);
            return null;
        }
    }
    
    /**
     * JSON字符串转对象（支持泛型）
     * 
     * @param json JSON字符串
     * @param typeReference 类型引用
     * @param <T> 泛型
     * @return 对象
     */
    public static <T> T fromJson(String json, TypeReference<T> typeReference) {
        if (StringUtils.isEmpty(json) || typeReference == null) {
            return null;
        }
        
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (JsonProcessingException e) {
            log.error("JSON转对象失败: json={}, typeReference={}", json, typeReference, e);
            return null;
        }
    }
    
    /**
     * JSON字符串转List
     * 
     * @param json JSON字符串
     * @param clazz 元素类型
     * @param <T> 泛型
     * @return List
     */
    public static <T> List<T> fromJsonToList(String json, Class<T> clazz) {
        if (StringUtils.isEmpty(json) || clazz == null) {
            return null;
        }
        
        try {
            return objectMapper.readValue(json, 
                    objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
        } catch (JsonProcessingException e) {
            log.error("JSON转List失败: json={}, class={}", json, clazz, e);
            return null;
        }
    }
    
    /**
     * JSON字符串转Map
     * 
     * @param json JSON字符串
     * @return Map
     */
    public static Map<String, Object> fromJsonToMap(String json) {
        if (StringUtils.isEmpty(json)) {
            return null;
        }
        
        try {
            return objectMapper.readValue(json, Map.class);
        } catch (JsonProcessingException e) {
            log.error("JSON转Map失败: json={}", json, e);
            return null;
        }
    }
    
    /**
     * JSON字符串转Map（指定值类型）
     * 
     * @param json JSON字符串
     * @param valueClass 值类型
     * @param <V> 值泛型
     * @return Map
     */
    public static <V> Map<String, V> fromJsonToMap(String json, Class<V> valueClass) {
        if (StringUtils.isEmpty(json) || valueClass == null) {
            return null;
        }
        
        try {
            return objectMapper.readValue(json, 
                    objectMapper.getTypeFactory().constructMapType(Map.class, String.class, valueClass));
        } catch (JsonProcessingException e) {
            log.error("JSON转Map失败: json={}, valueClass={}", json, valueClass, e);
            return null;
        }
    }
    
    /**
     * 对象转Map
     * 
     * @param obj 对象
     * @return Map
     */
    public static Map<String, Object> objectToMap(Object obj) {
        if (obj == null) {
            return null;
        }
        
        try {
            return objectMapper.convertValue(obj, Map.class);
        } catch (Exception e) {
            log.error("对象转Map失败: {}", obj, e);
            return null;
        }
    }
    
    /**
     * Map转对象
     * 
     * @param map Map
     * @param clazz 对象类型
     * @param <T> 泛型
     * @return 对象
     */
    public static <T> T mapToObject(Map<String, Object> map, Class<T> clazz) {
        if (map == null || clazz == null) {
            return null;
        }
        
        try {
            return objectMapper.convertValue(map, clazz);
        } catch (Exception e) {
            log.error("Map转对象失败: map={}, class={}", map, clazz, e);
            return null;
        }
    }
    
    /**
     * 深拷贝对象
     * 
     * @param obj 原对象
     * @param clazz 对象类型
     * @param <T> 泛型
     * @return 拷贝对象
     */
    public static <T> T deepCopy(T obj, Class<T> clazz) {
        if (obj == null || clazz == null) {
            return null;
        }
        
        try {
            String json = toJson(obj);
            return fromJson(json, clazz);
        } catch (Exception e) {
            log.error("深拷贝对象失败: obj={}, class={}", obj, clazz, e);
            return null;
        }
    }
    
    /**
     * 检查字符串是否为有效的JSON
     * 
     * @param json JSON字符串
     * @return 是否有效
     */
    public static boolean isValidJson(String json) {
        if (StringUtils.isEmpty(json)) {
            return false;
        }
        
        try {
            objectMapper.readTree(json);
            return true;
        } catch (JsonProcessingException e) {
            return false;
        }
    }
    
    /**
     * 获取ObjectMapper实例
     * 
     * @return ObjectMapper
     */
    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }
}
